package web.sms.core.shiro.filter;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.springframework.beans.factory.annotation.Autowired;
import web.sms.core.exception.ServiceException;
import web.sms.core.pojo.JsonInfo;
import web.sms.mvc.entity.User;
import web.sms.mvc.service.UserService;
import web.sms.utils.HttpUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * Created by Eoly on 2017/7/19.
 */
public class UsedRememberMeFilter extends UserFilter implements AjaxFilter {
    private Integer error = 405;
    private String msg = "";
    private Set<String> unCheckUrls = new LinkedHashSet<String>();

    private final UserService userService;

    @Autowired
    public UsedRememberMeFilter(UserService userService) {
        this.userService = userService;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (this.isUnCheckUrl(request, response)) {
            return true;
        } else {
            Subject subject = this.getSubject(request, response);
            String username = (String) subject.getPrincipal();
            if (username == null) {
                return false;
            }
            // 将用户信息写入到Session
            User u = (User) subject.getSession().getAttribute("userLogged");
            if (u == null) {
                try {
                    u = userService.findUserWithAuthenticationInfo(username);
                } catch (ServiceException e) {
                    if (e.getError().equals(404)) {
                        if (HttpUtils.isAjaxRequestInternal(request)) {
                            HttpUtils.outPrint(response, new JsonInfo(e.getError(), e.getMessage()));
                        } else {
                            HttpUtils.forwardAndSentAttributes(
                                    HttpUtils.toHttp(request), HttpUtils.toHttp(response), "/error",
                                    new JsonInfo(e.getError(), e.getMessage()));
                        }
                    }
                }
                subject.getSession().setAttribute("userLogged", u);
            }
            return true;
        }
    }

    @Override
    protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
        if (!isAjax(request)) {
            super.saveRequestAndRedirectToLogin(request, response);
        } else {
            doAjaxResponse(response);
        }
    }

    @Override
    public void doAjaxResponse(ServletResponse response) {
        HttpUtils.outPrint(response, new JsonInfo(error, msg));
    }

    @Override
    public boolean isAjax(ServletRequest request) {
        return HttpUtils.isAjaxRequestInternal(request);
    }

    private boolean isUnCheckUrl(ServletRequest request, ServletResponse response) {
        for (String url : unCheckUrls) {
            if (this.pathsMatch(url, request)) {
                return true;
            }
        }
        return false;
    }

    public Integer getError() {
        return error;
    }

    public void setError(Integer error) {
        this.error = error;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Set<String> getUnCheckUrls() {
        return unCheckUrls;
    }

    public void setUnCheckUrls(Set<String> unCheckUrls) {
        this.unCheckUrls = unCheckUrls;
    }
}
